package com.dennytech.tac.widget;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.util.Collections;
import java.util.Map;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;

import com.dennytech.tac.net.HttpClientFactory;
import com.dennytech.tac.net.HttpClientFactory.MyHttpClient;
import com.dennytech.tac.utils.Log;
import com.dennytech.tac.utils.WatchedOutputStream;
import com.dianping.localcache.ByteArrayCacheManager;
import com.dianping.localcache.CacheManager;

@SuppressWarnings(value={"unchecked"})
public class NetworkPhotoView extends NetworkImageView {

	private static final String TAG = NetworkPhotoView.class.getSimpleName();

	static boolean isCacheInited;

	static CacheManager<byte[]> cache = CacheManager.EMPTY;

	public static void init(Context context) {
		if (isCacheInited)
			return;
		isCacheInited = true;
		File file = new File(context.getCacheDir(), "photo");
		SQLiteDatabase db = null;
		try {
		    db = SQLiteDatabase.openOrCreateDatabase(file, null);
		} catch (Exception e) {
			Log.e(TAG, "init failed", e);
		}
		if (db != null) {
		    cache = new ByteArrayCacheManager(db, 3600000, 4 * 0x100000); // 1h, 4m
		}
		((ByteArrayCacheManager) cache).cleanUp();
	}

	public static void clear() {
		cache.clear();
	}

	public NetworkPhotoView(Context context) {
		super(context);
	}

	public NetworkPhotoView(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	public NetworkPhotoView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
	}

	protected Bitmap bitmap;
	int currentBytes;
	int totalBytes;
	String percent = " ";
	private Paint defaultPaint;

	@Override
	public void setDrawable(Drawable d, boolean isPlaceholder) {
		super.setDrawable(d, isPlaceholder);
		if (bitmap != null) {
			bitmap.recycle();
			bitmap = null;
		}
		if (!isPlaceholder && d instanceof BitmapDrawable) {
			bitmap = ((BitmapDrawable) d).getBitmap();
		}
	}

	@Override
	protected boolean discard() {
		currentBytes = 0;
		totalBytes = 0;
		return super.discard();
	}

	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		if (Boolean.FALSE.equals(imageRetrieve) && totalBytes > 0) {
			if (percent == "flag" || percent == "")
				percent = "";
			else
				percent = currentBytes * 100 / totalBytes + "%";
			if (defaultPaint == null) {
				defaultPaint = new Paint();

				defaultPaint.setColor(getContext().getResources().getColor(
						android.R.color.primary_text_light));
				defaultPaint.setTextAlign(Paint.Align.CENTER);
				defaultPaint.setTextSize(12 * getResources()
						.getDisplayMetrics().density);
			}
			canvas.drawText(percent, getWidth() / 2, getHeight() / 2
					- defaultPaint.ascent(), defaultPaint);
		}
	}

	@Override
	protected Map<String, Bitmap> memcache() {
		return Collections.EMPTY_MAP;
	}

	@Override
	protected LoadTask createLoadTask() {
		return new CachedLoadTask(this);
	}

	protected static class CachedLoadTask extends LoadTask {
		public CachedLoadTask(NetworkImageView p) {
			super(p);
		}

		@Override
		public Bitmap preDoInBackground(String... params) {
			final String url = params[0];

			//
			// check cache
			//
			byte[] bytes = cache.get(url);
			if (bytes != null) {
				try {
					return BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
				} catch (Exception e) {
					Log.e(TAG, "cachedloadtask predo failed", e);
				}
			}

			return null;
		}

		@Override
		public Bitmap doInBackground(String... params) {
			final String url = params[0];
			urlLocks.lock(url);
			MyHttpClient httpClient = null;
			try {
				if (isCancelled())
					return null;

				//
				// download from network
				//
				byte[] bytes = null;
				httpClient = HttpClientFactory.getHttpClient();
				Log.d(TAG, "url: " + url);
				HttpGet get = new HttpGet(url);
				this.get = get;
//				HttpHost proxy = DPEnv.agent().globalProxy();
//				ConnRouteParams.setDefaultProxy(get.getParams(), proxy);
				HttpResponse response = httpClient.execute(get);
				HttpEntity entity = response.getEntity();
				if (this.get == get
						&& response.getStatusLine().getStatusCode() / 100 == 2) {
					final int len = Math.max(0xFFF,
							(int) entity.getContentLength());
					ByteArrayOutputStream bos = new ByteArrayOutputStream(len);
					WatchedOutputStream wos = new WatchedOutputStream(bos);
					wos.setListener(new WatchedOutputStream.Listener() {
						@Override
						public void notify(int write) {
							NetworkImageView niv = parent.get();
							if (niv == null)
								return;
							NetworkPhotoView npv = (NetworkPhotoView) niv;
							npv.totalBytes = len;
							npv.currentBytes += write;
							npv.postInvalidate();
						}
					});
					entity.writeTo(wos);
					bytes = bos.toByteArray();
					Log.i(TAG, "image size: " + bytes.length / 1000 + "K");
				}
				entity.consumeContent();
				if (this.get != get)
					return null;
				else if (bytes == null)
					return null;
				else {
					Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0,
							bytes.length);
					if (bitmap != null) {
						cache.put(url, bytes);
					}
					return bitmap;
				}
			} catch (Exception e) {
				return null;
			} catch (Error e) {
				return null;
			} finally {
				this.get = null;
				if (httpClient != null)
					httpClient.recycle();
				urlLocks.unlock(url);
			}
		}
	}
}
